#!/usr/bin/env python
# _*_ coding: utf-8 _*_

from kubernetes import client, config
from kubernetes.stream import stream
import tarfile
from tempfile import TemporaryFile
from kubernetes.client.rest import ApiException
from os import path
import traceback
from log.logger import logger


def exec_cmd_in_pod(api_instance, pod_name, cmd, container=None, namespace='default', timeout=10):
    try:
        command = [
            "/bin/bash",
            "-c",
        ]
        command.append(cmd)
        api_response = stream(api_instance.connect_get_namespaced_pod_exec, pod_name, namespace,
                              command=command, container=container,
                              stderr=True, stdin=False,
                              stdout=True, tty=False,
                              _preload_content=False,
                              _request_timeout=timeout)
    except Exception as e:
        msg = 'Exec cmd "%s" in pod "%s" failed, the detail error msg is:"%s"' % (cmd, traceback.format_exc())
        print(msg)
        logger.error(msg)
        exit(-1)

    api_response.update(timeout=1)
    try:
        stdout = api_response.read_stdout()
    except Exception:
        stdout = "Got no stdout"
    try:
        stderr = api_response.read_stderr()
    except Exception:
        stderr = 'Got no stderr'
    return stdout, stderr


def copy_file_into_pod(api_instance, pod_name, src_path, dest_path, namespace='default', container=None):
    """
    This function copies a file into the pod
    :param api_instance: coreV1Api()
    :param name: pod name
    :param ns: pod namespace
    :param source_file: Path of the file to be copied into pod
    :return: nothing
    """

    try:
        exec_command = ['tar', 'xvf', '-', '-C', '/']
        api_response = stream(api_instance.connect_get_namespaced_pod_exec, pod_name, namespace,
                              command=exec_command, container=container,
                              stderr=True, stdin=True,
                              stdout=True, tty=False,
                              _preload_content=False)
        with TemporaryFile() as tar_buffer:
            with tarfile.open(fileobj=tar_buffer, mode='w') as tar:
                tar.add(src_path, dest_path)

            tar_buffer.seek(0)
            commands = []
            commands.append(tar_buffer.read())

            while api_response.is_open():
                api_response.update(timeout=1)
                if api_response.peek_stdout():
                    pass
                    #print('STDOUT: {0}'.format(api_response.read_stdout()))
                if api_response.peek_stderr():
                    pass
                    #print('STDERR: {0}'.format(api_response.read_stderr()))
                if commands:
                    c = commands.pop(0)
                    api_response.write_stdin(c.decode())
                else:
                    break
            api_response.close()
    except ApiException as e:
        print('Exception when copying file to the pod [%s] [%s]: %s \n' % (pod_name, container, e))
        exit(-1)


def exec_script_in_pod(api_instance, pod_name, script_path, container=None, namespace='default', timeout=10):
    script_name = script_path.strip().split('/')[-1].strip()
    dest_path = "/tmp/%s" % script_name
    copy_file_into_pod(
        api_instance=api_instance,
        pod_name=pod_name,
        src_path=script_path,
        dest_path=dest_path,
        container=container,
        namespace=namespace,
    )
    exec_cmd_in_pod(
        api_instance=api_instance,
        pod_name=pod_name,
        cmd="chmod +x %s" % dest_path,
        container=container,
        namespace=namespace,
        timeout=timeout
    )
    exec_cmd_in_pod(
        api_instance=api_instance,
        pod_name=pod_name,
        cmd="%s >> ~/exec_cmd.log 2>&1" % dest_path,
        container=container,
        namespace=namespace,
        timeout=timeout
    )
    exec_cmd_in_pod(
        api_instance=api_instance,
        pod_name=pod_name,
        cmd="rm -f %s" % dest_path,
        container=container,
        namespace=namespace,
        timeout=timeout
    )


def copy_file_from_pod(api_instance, pod_name, src_path, dest_path, container=None, namespace="default"):
    """
    :param pod_name:
    :param src_path:
    :param dest_path:
    :param namespace:
    :return:
    """

    dir = path.dirname(src_path)
    bname = path.basename(src_path)
    exec_command = ['/bin/sh', '-c', 'cd {src}; tar cf - {base}'.format(src=dir, base=bname)]

    with TemporaryFile() as tar_buffer:
        resp = stream(api_instance.connect_get_namespaced_pod_exec, pod_name, namespace,
                      command=exec_command,
                      container=container,
                      stderr=True, stdin=True,
                      stdout=True, tty=False,
                      _preload_content=False)

        while resp.is_open():
            resp.update(timeout=1)
            if resp.peek_stdout():
                out = resp.read_stdout()
                # print("STDOUT: %s" % len(out))
                tar_buffer.write(out.encode('utf-8'))
            if resp.peek_stderr():
                print('STDERR: {0}'.format(resp.read_stderr()))
        resp.close()

        tar_buffer.flush()
        tar_buffer.seek(0)

        with tarfile.open(fileobj=tar_buffer, mode='r:') as tar:
            subdir_and_files = [
                tarinfo for tarinfo in tar.getmembers()
            ]
            tar.extractall(path=dest_path, members=subdir_and_files)